package faf.business;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;

import faf.entities.Account;
import faf.entities.Answer;
import faf.entities.Confidentiality;
import faf.entities.Properties;
import faf.entities.Question;
import faf.entities.QuestionType;
import faf.entities.Sheet;
import faf.entities.SheetState;
import faf.entities.Survey;

public class ReportManager extends BaseManager {
	
	SurveyManager surveyManager;
	
	public SurveyManager getSurveyManager() {
		return surveyManager;
	}

	public void setSurveyManager(SurveyManager surveyManager) {
		this.surveyManager = surveyManager;
	}

	/**
	 * Permet de savoir si un user representé par un objet Account 
	 * peut acceder au rapport graphique
	 * @param user
	 * @param survey
	 * @return
	 */
	public boolean canSeeGraphicalReport(Account user, Survey survey) {
		if (survey.getConfidentiality() == Confidentiality.PRIVATE
				&& user != null && survey.getAccount().getMail().equals(user.getMail())) {
			return true;
		}
		
		if (survey.getConfidentiality() == Confidentiality.SEMIPRIVATE
				&& user != null && getSurveyManager().isSurveyTarget(survey, user)) {
			return true;
		}
		
		if (survey.getConfidentiality() == Confidentiality.PUBLIC) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * Permet de savoir si un utilisateur peut acceder au rapport complet
	 * @param user
	 * @param survey
	 * @return
	 */
	public boolean canSeeFullreport(Account user, Survey survey) {
		
		if (survey.getConfidentiality() == Confidentiality.PRIVATE
				&& user != null && survey.getAccount().getMail().equals(user.getMail())) {
			return true;
		}
		
		if ((survey.getConfidentiality() == Confidentiality.SEMIPRIVATE
				|| survey.getConfidentiality() == Confidentiality.PUBLIC)
				&& user != null && surveyManager.isSurveyTarget(survey, user)) {
			return true;
		}
				
		
		return false;
	}
	
	/**
	 * Permet de recuperer le rapport complet,
	 * Le rapport complet est representé par une liste de liste de String qui 
	 * va être utilisé pour générer le tableau.
	 * Le premier élèment correspond à l'entete de du tableau. Le premier élèment 
	 * de l'entete est "email" (sans les guillements), les champs suivants de 
	 * l'entete sont les questions.
	 * Les listes suivantes commencent par l'email de l'Utillisateur, les champs 
	 * suivant contiennent les réponses de l'utilisateurs dans le bon ordre.
	 * 
	 * Les reponses fichiers sont representés sous forme de lien html pret à être
	 * rendu. Cette implementation est lié à l'application est l'url est du type :
	 * est relative : "attachment.htm?answer_id=XXX"
	 * 
	 * @param survey_id
	 * @return
	 */
	public List getFullReport(long survey_id) {
		EntityManager em = null;
		try {
			em = jpautils.createEntityManger();
			Survey survey = em.find(Survey.class, survey_id);
			List<List<String>> report = new LinkedList<List<String>>();
			
			List<Question> questions = survey.getQuestionList();
			List<String> header = new LinkedList<String>();
			
			header.add("email");
			
			for(Question question : questions) {
				header.add(question.getTitle());
			}
			
			report.add(header);
			
			for(Sheet sheet : survey.getSheetList()) {
				List<String> answers = new LinkedList<String>();
				answers.add(sheet.getAccount().getMail());
				
				for(Answer answer : sheet.getAnswerList()) {
					QuestionType type = answer.getQuestion().getType();
					if (type.equals(QuestionType.FILE)) {
						answers.add("<a href=\"attachment.htm?answer_id=" + answer.getId()+"\">"+answer.getValue() + "</a>");
					}
					if(type.equals(QuestionType.SIMPLECHOICE)) {
						String value = em.find(Properties.class, Long.parseLong(answer.getValue())).getValue();
						answers.add(value);
					}
					if(type.equals(QuestionType.STRING) || type.equals(QuestionType.TEXT)) {
						String value = answer.getValue();
						answers.add(value);						
					}
				}
				
				if (answers.size() < header.size()) {
					int delta =  header.size() - answers.size();
					for(int i = 0; i < delta; i++) {
						answers.add("");
					}
				}
				
				report.add(answers);
			}
			
			return report;
		} finally {
			if (em != null)
				em.close();
		}
	}
	
	
	/**
	 * Retourne une liste de Map correspondants à tous les questions à choix simple 
	 * du sondage ayant pour id survey_id.
	 * 
	 * La Map contient 3 élèments :
	 *   * "question" contient la question sous forme de String
	 *   * "statistiques" est une liste de liste de Map, où la Map met 
	 *   en correspondances une reponse avec le nombre de personne ayant
	 *   choisit cette réponse. 
	 * 
	 * @param survey_id
	 * @return
	 */
	public List getSimpleChoiceStatistics(long survey_id) {
		EntityManager em = null;
		try {
			List results = new LinkedList();
			
	        em = jpautils.createEntityManger();
	        Survey survey = em.find(Survey.class, survey_id);
	        List<Question> questions = survey.getQuestionList();

	        for(Question question : questions) {
	        	if(question.getType().equals(QuestionType.SIMPLECHOICE)) {
	        		Map question_map = new HashMap();
	        		question_map.put("question", question.getTitle());
	        		
	        		List<Answer> answers = question.getAnswer();
	        		Map<String, Integer> stats = new HashMap<String, Integer>();
	        		
	        		for(Properties property : question.getProperties()) {
	        			stats.put(property.getValue(), 0);
	        		}
	        		
	        		for(Answer answer: answers) {
	        			if(answer.getSheet().getState().equals(SheetState.COMPLETE)) {
	        				Properties property = em.find(Properties.class, Long.parseLong(answer.getValue()));
	        				Integer old_value = stats.get(property.getValue());
	        				stats.put(property.getValue(), old_value+1);
	        			}
	        		}
	        		question_map.put("statistiques", stats);
	        		
	        		results.add(question_map);
	        	}
	        }
	        
			return results;
		} finally {
			if (em != null)
				em.close();
		}		
	}
	
	
	/**
	 * Permet de recuperer les statistiques de l'état des fiches pour le sondage 
	 * ayant pour id survey_id.
	 * 
	 * La valeur renvoyé est une Map mettant en correspondance la representation 
	 * sous forme de string des états, avec le nombre de fiche dans cette état.
	 * 
	 * @param survey_id
	 * @return
	 */
	public Map getStateStatistics(long survey_id) {
		EntityManager em = null;
		try {
			Map<String, Integer> results = new HashMap<String, Integer>();
	        results.put(SheetState.COMPLETE.toString(), 0);
	        results.put(SheetState.CURRING.toString(), 0);
	        results.put(SheetState.PENDING.toString(), 0);
	        results.put(SheetState.REFRESH.toString(), 0);
	        
	        em = jpautils.createEntityManger();
	        Survey survey = em.find(Survey.class, survey_id);
	        List<Sheet> sheets = survey.getSheetList();
	        
	        for (Sheet sheet : sheets) {
	             String state = sheet.getState().toString();
	             Integer old_value = results.get(state);
	             results.put(state, old_value+1);
	        }
	        
	        
	        
			return results;
		} finally {
			if (em != null)
				em.close();
		}
	}

	/**
	 * Renvoie une liste de liste de String qui permet de generer le fichier csv.
	 * 
	 * cf. getFullReport pour une description du format, la différence est qu'ici
	 * les string sont entre guillement et les reponses fichier ne sont pas supportés
	 * 
	 * @param survey_id
	 * @return
	 */
	public List<List<String>> getFullCsvReport(long survey_id) {
		EntityManager em = null;
		try {
			em = jpautils.createEntityManger();
			Survey survey = em.find(Survey.class, survey_id);
			List<List<String>> report = new LinkedList<List<String>>();
			
			List<Question> questions = survey.getQuestionList();
			List<String> header = new LinkedList<String>();
			
			header.add("email");
			
			for(Question question : questions) {
				header.add(question.getTitle());
			}
			
			report.add(header);
			
			for(Sheet sheet : survey.getSheetList()) {
				List<String> answers = new LinkedList<String>();
				answers.add(sheet.getAccount().getMail());
				
				for(Answer answer : sheet.getAnswerList()) {
					QuestionType type = answer.getQuestion().getType();
					if (type.equals(QuestionType.FILE)) {
						answers.add("");
					}
					if(type.equals(QuestionType.SIMPLECHOICE)) {
						String value = em.find(Properties.class, Long.parseLong(answer.getValue())).getValue();
						answers.add("\""+value+"\"");
					}
					if(type.equals(QuestionType.STRING) || type.equals(QuestionType.TEXT)) {
						String value = answer.getValue();
						answers.add("\""+value+"\"");						
					}
				}
				
				if (answers.size() < header.size()) {
					int delta =  header.size() - answers.size();
					for(int i = 0; i < delta; i++) {
						answers.add("");
					}
				}
				
				report.add(answers);
			}
			
			return report;
		} finally {
			if (em != null)
				em.close();
		}
	}
}
